/*
 * Copyright (C) 2014 Félix Marín Ramírez | felixmurcia@gmail.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package calculadora.controlador;

import calculadora.modelo.ModeloPrimos;
import calculadora.vista.primos.VistaCalcPrimos;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

/**
 *
 * @author Félix Marín Ramírez | felixmurcia@gmail.com
 */
public class ControlPrimos {

    private VistaCalcPrimos vcPrimos;
    private ModeloPrimos mPrimos;
    private int primo;
    private boolean interruptor;
    private SwingWorker worker;
    private int posicion;
    private int contador;
    private ArrayList<JProgressBar> listaBarras;

    /**
     * Constructor de la clase.
     *
     * @param vcPrimos Recibe como parametro un objeto tipo VistaCalcPrimos.
     */
    public ControlPrimos(VistaCalcPrimos vcPrimos) {
        this.vcPrimos = vcPrimos;
        this.mPrimos = new ModeloPrimos();
        this.interruptor = true;
        this.contador = 0;
    }

    /**
     *
     * @param posicion Parámetro de tipo int, el cua, indica la posición del
     * númro primo.
     */
    public void setPosicion(int posicion) {
        this.posicion = posicion;
    }

    /**
     *
     * @return Devuelve el número de Barras de progreso creadas.
     */
    public int getContador() {
        return contador;
    }

    /**
     *
     * @param next Parametro de tipo int que añade un número al contador.
     */
    public void setContador(int next) {
        this.contador = next;
    }

    /**
     * Metodo usado para cancelar el progreso de la barra.
     */
    public void stop() {
        try {
            worker.cancel(true);
        } catch (CancellationException ex) {
            //DO NOTHING
        }
    }

    /**
     * Método usado para reanuadar el progreso de la barra.
     */
    public void start() {
        interruptor = true;
    }

    /**
     * Método encargado de realizar operaciones pesadas en un hilo aparte de
     * tipo walker.
     *
     * @param evt Parámetro que corresponde a un evento.
     */
    public void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

        worker = new SwingWorker<Integer, Integer>() {
            @Override
            public void done() {
                try {
                    if (!interruptor) {
                        stop();
                    } else {
                        vcPrimos.getTab1().addTexto(vcPrimos.getTab1().getTxtArea().getText()
                                + "Posición "
                                + posicion
                                + " --> Número "
                                + String.valueOf(get()));
                    }
                } catch (InterruptedException | ExecutionException ignore) {
                    vcPrimos.getTab1().mensajeError(ignore);
                }
            }

            @Override
            protected Integer doInBackground() throws Exception {

                int[] primos = mPrimos.primos(posicion);
                mPrimos.setNumInt(0);

                for (int i = 0; i < posicion; i++) {
                    Thread.sleep(100);
                    publish(i);
                    setProgress(i / 20);
                }

                if (!interruptor) {
                    stop();
                    cancel(true);
                    setProgress(0);
                } else {
                    setProgress(100);
                }
                primo = (int) primos[posicion - 1];
                return primo;
            }

            @Override
            public void process(List<Integer> values) {
                // Estoy en el hilo de eventos 
                // => puedo modificar la interfaz
                for (int i = 0; i < values.size(); i++) {
                    Integer d = values.get(i);
                }
            }
        };

        // Añado el listener para que modifique 
        // la barra de progreso con el progreso de la tarea
        worker.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if ("progress".equals(evt.getPropertyName())) {
                    int progress = (Integer) evt.getNewValue();
                    for (int i = 0; i <= contador; i++) {
                        vcPrimos.getTab2().setProgress(i, progress);
                    }
                }
            }
        });

        // Ejecuto la tarea
        this.worker.execute();
    }

    /**
     * Método encargado de recargar las barras de progreso en la clase
     * VistaPrimTab2 y después repintarla.
     */
    public void recargar() {
        listaBarras = new ArrayList<>();
        for (int i = 0; i < contador; i++) {
            vcPrimos.getTab2().getProgressBar(i).setVisible(true);
            listaBarras.add(vcPrimos.getTab2().getProgressBar(i));
        }
        vcPrimos.getTab2().getJPanel().removeAll();
        vcPrimos.getTab2().getProgressBar(contador).setVisible(true);
        listaBarras.add(vcPrimos.getTab2().getProgressBar(contador));

        for (JProgressBar jProgressBar : listaBarras) {
            vcPrimos.getTab2().getJPanel().add(jProgressBar);
        }
        vcPrimos.getTab2().getJPanel().repaint();
        vcPrimos.getTab2().getJScrollPane().repaint();
        vcPrimos.repaint();
    }
}
